Regular expressions

Cyclone has an interface to the [Perl Compatible Regular Expressions][1] (PCRE) library.

Here’s a Perl program that does a simple substitution:

my $x = "Hello, Bob";
$x =~ s/Bob/World/;
print $x, "\n";

It prints “Hello, World.” The equivalent Cyclone program is

#include <stdio.h>
#include <pcre.h>

int main() {
  let x = "Hello, Bob";
  let y = pcre_s(x,"Bob","World",0);
  printf("%s\n",y);
  return 0;
}

You need to compile this program with the -lpcre flag.

A global replacement, like the Perl s/foo/bar/g, is done with

y = pcre_s_g(x,"foo","bar",0);

The last argument of pcre_s and pcre_s_g allows you to set options for the substitution. For example the Perl s/(foo|bar)baz/$1/gms corresponds to

y = pcre_s_g(x,"(foo|bar)baz","$1",PCRE_MULTILINE|PCRE_DOTALL);

The options you can pass this way are PCRE_MULTILINE (for m), PCRE_DOTALL (for s), PCRE_CASELESS (for i), and PCRE_EXTENDED (for x).

The Perl option e allows you to execute Perl statements at each match in the substitution, for example,

s{([A-Z]+)}{lc($1)}e

matches every word in upper case only, and converts that text to lower case using the function lc. The result of the evaluation should be a string that is the replacement value.

The equivalent in Cyclone would be

y = PCRE_S_EG(x,"([A-Z]+)",
              ({ let one = DOLLAR(1);
                 STRING(lc(one)); }),
              0);

PCRE_S_EG is a macro. The third argument of the macro is an expression to be executed at each match. Here, we have used a statement expression, which allows us to use declarations, etc. The macro DOLLAR returns a new, heap-allocated copy of the corresponding match (so DOLLAR(1) is like $1 in Perl). The macro STRING adds its argument to the replacement text.